//
//  PSLevelsTests.m
//  PrefCore
//
//  Created by Sergey on 2/18/14.
//  Copyright (c) 2014 Play-on-smart. All rights reserved.
//

#import <XCTest/XCTest.h>
#import "PSLevels.h"
#import "PSErrors.h"

@interface PSLevelsTests : XCTestCase {

    PSGameSettings *gs;
    PSGame *game;
}

@end

@implementation PSLevelsTests

-(void)setUp {
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    [PSGameSettings clearUserDefaults:ud];
    [ud synchronize];
    gs = [PSGameSettings settingsFromUserDefaults:ud];
    game = [[PSGame alloc] init];
}

-(NSData*)dataForResourcePath:(NSString*)path {
    NSBundle *bundle = [NSBundle bundleForClass:[PSLevelsTests class]];
    NSString *jsonPath = [bundle pathForResource:path ofType:@"txt"];
    return [NSData dataWithContentsOfFile:jsonPath];
}

- (void)testIncompleteMap {
    NSError *err;
    BOOL res = [PSLevels updateWithData:[self dataForResourcePath:@"TestLevelsErr01-JSON"] error:&err];
    XCTAssertFalse(res, @"Err01 contains an incomplete set of data.");
    XCTAssertEqualObjects(err.domain, PSPrefErrorDomain);
    XCTAssertEqual(err.code, (NSInteger)PS_ERROR_MISSING_DATA);
    XCTAssertNotNil(err.userInfo);
    NSString *missingKeys = [err.userInfo valueForKey:PSErrorMissingDataKey];
    XCTAssertEqualObjects(missingKeys, @"misere, trickingStanding");
}

-(void)testInvalidArrays {
    for (int i = 2 ; i <= 7 ; i++) {
        NSString *testResourcePath = [NSString stringWithFormat:@"TestLevelsErr0%d-JSON", i];
        NSError *err;
        BOOL res = [PSLevels updateWithData:[self dataForResourcePath:testResourcePath] error:&err];
        XCTAssertFalse(res, @"Err0%d contains incomplete data; must error.", i);
        XCTAssertEqualObjects(err.domain, PSPrefErrorDomain);
        XCTAssertEqual(err.code, (NSInteger)PS_ERROR_INVALID_DATA);
        XCTAssertEqual(err.userInfo.count, 0UL);
    }
}

-(void)testSuccessfulRead {
    NSError *err;
    BOOL res = [PSLevels updateWithData:[self dataForResourcePath:@"TestLevels-JSON"] error:&err];
    XCTAssertTrue(res, @"TestLevels-JSON file contains a correct Levels definition.");
}

-(void)testBestMoveZeroPlayerId {
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:0]);
}

-(void)testBestMoveAfterPass {
    game.hand = 1;
    game.lastBid = [PSBid bidPlayWithTrump:kSuitClubs tricks:6];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

-(void)testBestMovePassingEmpty {
    game.hand = 1;
    game.lastBid = [PSBid bidPass];
    game.rounds = 4;
    [gs setLevel:kGameLevel0 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 8;
    [gs setLevel:kGameLevel1 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    [gs setLevel:kGameLevel2 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 9;
    [gs setLevel:kGameLevel3 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

-(void)testBestMovePassingNonEmpty {
    game.hand = 1;
    game.lastBid = [PSBid bidPass];
    game.rounds = 3;
    [gs setLevel:kGameLevel0 forPlayerId:1];
    XCTAssertEqual(1, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 1;
    [gs setLevel:kGameLevel1 forPlayerId:1];
    XCTAssertEqual(3, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 0;
    [gs setLevel:kGameLevel2 forPlayerId:1];
    XCTAssertEqual(6, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 1;
    [gs setLevel:kGameLevel3 forPlayerId:1];
    XCTAssertEqual(8, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

-(void)testBestMoveStandingEmpty {
    game.hand = 0;
    game.movingTye = kMovingTypeStanding;
    game.lastBid = [PSBid bidPlayWithTrump:kSuitClubs tricks:6];
    game.rounds = 4;
    [gs setLevel:kGameLevel0 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 6;
    [gs setLevel:kGameLevel1 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 7;
    [gs setLevel:kGameLevel2 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 9;
    [gs setLevel:kGameLevel3 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

-(void)testBestMoveStandingNonEmpty {
    game.hand = 0;
    game.movingTye = kMovingTypeStanding;
    game.lastBid = [PSBid bidPlayWithTrump:kSuitClubs tricks:6];
    game.rounds = 3;
    [gs setLevel:kGameLevel0 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 1;
    [gs setLevel:kGameLevel1 forPlayerId:1];
    XCTAssertEqual(3, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 1;
    [gs setLevel:kGameLevel2 forPlayerId:1];
    XCTAssertEqual(4, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 0;
    [gs setLevel:kGameLevel3 forPlayerId:1];
    XCTAssertEqual(8, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

-(void)testBestMoveOpenEmpty {
    game.hand = 0;
    game.movingTye = kMovingTypeOpen;
    game.lastBid = [PSBid bidPlayWithTrump:kSuitClubs tricks:6];
    game.rounds = 9;
    [gs setLevel:kGameLevel0 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 8;
    [gs setLevel:kGameLevel1 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 5;
    [gs setLevel:kGameLevel2 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 7;
    [gs setLevel:kGameLevel3 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

-(void)testBestMoveOpenNonEmpty {
    game.hand = 0;
    game.movingTye = kMovingTypeOpen;
    game.lastBid = [PSBid bidPlayWithTrump:kSuitClubs tricks:6];
    game.rounds = 3;
    [gs setLevel:kGameLevel0 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 1;
    [gs setLevel:kGameLevel1 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 1;
    [gs setLevel:kGameLevel2 forPlayerId:1];
    XCTAssertEqual(4, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 2;
    [gs setLevel:kGameLevel3 forPlayerId:1];
    XCTAssertEqual(4, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

-(void)testBestMoveMisereEmpty {
    game.hand = 0;
    game.lastBid = [PSBid bidMisere];
    game.rounds = 0;
    [gs setLevel:kGameLevel0 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 4;
    [gs setLevel:kGameLevel1 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 6;
    [gs setLevel:kGameLevel2 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 8;
    [gs setLevel:kGameLevel3 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

-(void)testBestMoveMisereNonEmpty {
    game.hand = 0;
    game.lastBid = [PSBid bidMisere];
    game.rounds = 3;
    [gs setLevel:kGameLevel0 forPlayerId:1];
    XCTAssertEqual(0, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 1;
    [gs setLevel:kGameLevel1 forPlayerId:1];
    XCTAssertEqual(1, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 1;
    [gs setLevel:kGameLevel2 forPlayerId:1];
    XCTAssertEqual(3, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
    game.rounds = 2;
    [gs setLevel:kGameLevel3 forPlayerId:1];
    XCTAssertEqual(6, [PSLevels bestMoveDepthWithGame:game settings:gs andPlayerId:1]);
}

@end
